ઉન્નત બ્રાઉઝર-આધારિત વિડિયો પ્રોસેસિંગને અનલૉક કરો. કસ્ટમ ઇફેક્ટ્સ અને વિશ્લેષણ માટે વેબકોડેક્સ API સાથે રો વિડિયોફ્રેમ પ્લેન ડેટાને સીધો એક્સેસ અને મેનિપ્યુલેટ કરવાનું શીખો.
વેબકોડેક્સ વિડિયોફ્રેમ પ્લેન એક્સેસ: રો વિડિયો ડેટા મેનિપ્યુલેશનમાં ઊંડાણપૂર્વકનો અભ્યાસ
વર્ષોથી, વેબ બ્રાઉઝરમાં ઉચ્ચ-પ્રદર્શન વિડિયો પ્રોસેસિંગ એક દૂરના સ્વપ્ન જેવું લાગતું હતું. ડેવલપર્સ ઘણીવાર <video> એલિમેન્ટ અને 2D કેનવાસ API ની મર્યાદાઓમાં સીમિત રહેતા હતા, જે શક્તિશાળી હોવા છતાં, પ્રદર્શનમાં અવરોધો ઉભા કરતા હતા અને અંતર્ગત રો વિડિયો ડેટા સુધી મર્યાદિત એક્સેસ આપતા હતા. વેબકોડેક્સ API ના આગમનથી આ પરિદ્રશ્ય મૂળભૂત રીતે બદલાઈ ગયું છે, જે બ્રાઉઝરના બિલ્ટ-ઇન મીડિયા કોડેક્સ સુધી નીચા-સ્તરનો એક્સેસ પૂરો પાડે છે. તેની સૌથી ક્રાંતિકારી વિશેષતાઓમાંની એક એ છે કે VideoFrame ઑબ્જેક્ટ દ્વારા વ્યક્તિગત વિડિયો ફ્રેમના રો ડેટાને સીધો એક્સેસ અને મેનિપ્યુલેટ કરવાની ક્ષમતા.
આ લેખ એવા ડેવલપર્સ માટે એક વ્યાપક માર્ગદર્શિકા છે જેઓ સરળ વિડિયો પ્લેબેકથી આગળ વધવા માગે છે. અમે VideoFrame પ્લેન એક્સેસની જટિલતાઓને શોધીશું, કલર સ્પેસ અને મેમરી લેઆઉટ જેવી વિભાવનાઓને સ્પષ્ટ કરીશું, અને તમને રિયલ-ટાઇમ ફિલ્ટર્સથી લઈને અત્યાધુનિક કમ્પ્યુટર વિઝન કાર્યો સુધી, ઇન-બ્રાઉઝર વિડિયો એપ્લિકેશન્સની આગામી પેઢી બનાવવા માટે સશક્ત બનાવવા માટે વ્યવહારુ ઉદાહરણો પ્રદાન કરીશું.
પૂર્વજરૂરીયાતો
આ માર્ગદર્શિકામાંથી સૌથી વધુ લાભ મેળવવા માટે, તમારી પાસે આની નક્કર સમજ હોવી જોઈએ:
- આધુનિક જાવાસ્ક્રિપ્ટ: અસિંક્રોનસ પ્રોગ્રામિંગ (
async/await, Promises) સહિત. - મૂળભૂત વિડિયો કન્સેપ્ટ્સ: ફ્રેમ્સ, રિઝોલ્યુશન અને કોડેક્સ જેવા શબ્દોથી પરિચિતતા મદદરૂપ થશે.
- બ્રાઉઝર APIs: Canvas 2D અથવા WebGL જેવા APIs સાથેનો અનુભવ ફાયદાકારક રહેશે પરંતુ તે સખત રીતે જરૂરી નથી.
વિડિયો ફ્રેમ્સ, કલર સ્પેસ અને પ્લેન્સને સમજવું
આપણે API માં ઊંડા ઉતરીએ તે પહેલાં, આપણે વિડિયો ફ્રેમના ડેટા ખરેખર કેવા દેખાય છે તેનું એક નક્કર માનસિક મોડેલ બનાવવું જોઈએ. ડિજિટલ વિડિયો એ સ્થિર છબીઓ, અથવા ફ્રેમ્સનો ક્રમ છે. દરેક ફ્રેમ પિક્સેલ્સની ગ્રીડ છે, અને દરેક પિક્સેલનો એક રંગ હોય છે. તે રંગ કેવી રીતે સંગ્રહિત થાય છે તે કલર સ્પેસ અને પિક્સેલ ફોર્મેટ દ્વારા વ્યાખ્યાયિત કરવામાં આવે છે.
RGBA: વેબની મૂળ ભાષા
મોટાભાગના વેબ ડેવલપર્સ RGBA કલર મોડેલથી પરિચિત છે. દરેક પિક્સેલ ચાર ઘટકો દ્વારા રજૂ થાય છે: લાલ, લીલો, વાદળી અને આલ્ફા (પારદર્શિતા). ડેટા સામાન્ય રીતે મેમરીમાં ઇન્ટરલીવ્ડ (interleaved) રીતે સંગ્રહિત થાય છે, જેનો અર્થ છે કે એક પિક્સેલ માટેના R, G, B, અને A મૂલ્યો ક્રમિક રીતે સંગ્રહિત થાય છે:
[R1, G1, B1, A1, R2, G2, B2, A2, ...]
આ મોડેલમાં, આખી છબી મેમરીના એક જ, સતત બ્લોકમાં સંગ્રહિત થાય છે. આપણે આને ડેટાનો એક જ "પ્લેન" હોવાનું વિચારી શકીએ છીએ.
YUV: વિડિયો કમ્પ્રેશનની ભાષા
વિડિયો કોડેક્સ, જોકે, ભાગ્યે જ સીધા RGBA સાથે કામ કરે છે. તેઓ YUV (અથવા વધુ સ્પષ્ટ રીતે, Y'CbCr) કલર સ્પેસ પસંદ કરે છે. આ મોડેલ છબીની માહિતીને આમાં વિભાજિત કરે છે:
- Y (લ્યુમા): તેજ અથવા ગ્રેસ્કેલ માહિતી. માનવ આંખ લ્યુમામાં થતા ફેરફારો પ્રત્યે સૌથી વધુ સંવેદનશીલ હોય છે.
- U (Cb) અને V (Cr): ક્રોમિનેન્સ અથવા રંગ-તફાવત માહિતી. માનવ આંખ તેજની વિગતો કરતાં રંગની વિગતો પ્રત્યે ઓછી સંવેદનશીલ હોય છે.
આ વિભાજન કાર્યક્ષમ કમ્પ્રેશન માટે ચાવીરૂપ છે. U અને V ઘટકોના રિઝોલ્યુશનને ઘટાડીને—એક તકનીક જેને ક્રોમા સબસમ્પલિંગ (chroma subsampling) કહેવાય છે—આપણે ગુણવત્તામાં ન્યૂનતમ અનુભવી શકાય તેવા નુકસાન સાથે ફાઇલનું કદ નોંધપાત્ર રીતે ઘટાડી શકીએ છીએ. આનાથી પ્લાનર (planar) પિક્સેલ ફોર્મેટ્સ બને છે, જ્યાં Y, U, અને V ઘટકો અલગ મેમરી બ્લોક્સ, અથવા "પ્લેન્સ" માં સંગ્રહિત થાય છે.
એક સામાન્ય ફોર્મેટ I420 (YUV 4:2:0 નો એક પ્રકાર) છે, જ્યાં પિક્સેલ્સના દરેક 2x2 બ્લોક માટે, ચાર Y સેમ્પલ હોય છે પરંતુ માત્ર એક U અને એક V સેમ્પલ હોય છે. આનો અર્થ એ છે કે U અને V પ્લેન્સની પહોળાઈ અને ઊંચાઈ Y પ્લેનની અડધી હોય છે.
આ તફાવતને સમજવો નિર્ણાયક છે કારણ કે વેબકોડેક્સ તમને આ જ પ્લેન્સ સુધી સીધો એક્સેસ આપે છે, બરાબર જેમ ડીકોડર તેમને પ્રદાન કરે છે.
VideoFrame ઑબ્જેક્ટ: પિક્સેલ ડેટા માટે તમારું પ્રવેશદ્વાર
આ કોયડાનો કેન્દ્રીય ભાગ VideoFrame ઑબ્જેક્ટ છે. તે વિડિયોના એક ફ્રેમનું પ્રતિનિધિત્વ કરે છે અને તેમાં માત્ર પિક્સેલ ડેટા જ નહીં પરંતુ મહત્વપૂર્ણ મેટાડેટા પણ હોય છે.
VideoFrameના મુખ્ય ગુણધર્મો
format: પિક્સેલ ફોર્મેટ સૂચવતો એક સ્ટ્રિંગ (દા.ત., 'I420', 'NV12', 'RGBA').codedWidth/codedHeight: મેમરીમાં સંગ્રહિત ફ્રેમના સંપૂર્ણ પરિમાણો, જેમાં કોડેક દ્વારા જરૂરી કોઈપણ પેડિંગનો સમાવેશ થાય છે.displayWidth/displayHeight: ફ્રેમ પ્રદર્શિત કરવા માટે ઉપયોગમાં લેવાતા પરિમાણો.timestamp: માઇક્રોસેકન્ડમાં ફ્રેમનો પ્રસ્તુતિ ટાઇમસ્ટેમ્પ.duration: માઇક્રોસેકન્ડમાં ફ્રેમનો સમયગાળો.
જાદુઈ મેથડ: copyTo()
રો પિક્સેલ ડેટાને એક્સેસ કરવા માટેની પ્રાથમિક મેથડ videoFrame.copyTo(destination, options) છે. આ અસિંક્રોનસ મેથડ ફ્રેમના પ્લેન ડેટાને તમે પ્રદાન કરેલા બફરમાં કૉપિ કરે છે.
destination: ડેટાને સમાવવા માટે પૂરતું મોટુંArrayBufferઅથવા ટાઇપ્ડ એરે (જેમ કેUint8Array).options: એક ઑબ્જેક્ટ જે સ્પષ્ટ કરે છે કે કયા પ્લેન્સને કૉપિ કરવા અને તેમનો મેમરી લેઆઉટ. જો અવગણવામાં આવે, તો તે બધા પ્લેન્સને એક જ સંલગ્ન બફરમાં કૉપિ કરે છે.
આ મેથડ એક પ્રોમિસ પરત કરે છે જે PlaneLayout ઑબ્જેક્ટ્સની એરે સાથે રિઝોલ્વ થાય છે, ફ્રેમમાં દરેક પ્લેન માટે એક. દરેક PlaneLayout ઑબ્જેક્ટમાં બે નિર્ણાયક માહિતી હોય છે:
offset: બાઇટ ઑફસેટ જ્યાં આ પ્લેનનો ડેટા ડેસ્ટિનેશન બફરમાં શરૂ થાય છે.stride: પિક્સેલ્સની એક હરોળની શરૂઆત અને તે પ્લેન માટે આગલી હરોળની શરૂઆત વચ્ચેના બાઇટ્સની સંખ્યા.
એક નિર્ણાયક ખ્યાલ: સ્ટ્રાઇડ વિ. વિડ્થ
નીચા-સ્તરના ગ્રાફિક્સ પ્રોગ્રામિંગમાં નવા ડેવલપર્સ માટે આ સૌથી સામાન્ય ગૂંચવણના સ્ત્રોતોમાંનો એક છે. તમે એવું માની ન શકો કે પિક્સેલ ડેટાની દરેક હરોળ એકબીજા પછી ચુસ્તપણે પેક થયેલી છે.
- વિડ્થ (Width) એ છબીની એક હરોળમાં પિક્સેલ્સની સંખ્યા છે.
- સ્ટ્રાઇડ (Stride) (જેને પિચ અથવા લાઇન સ્ટેપ પણ કહેવાય છે) એ મેમરીમાં એક હરોળની શરૂઆતથી આગલી હરોળની શરૂઆત સુધીના બાઇટ્સની સંખ્યા છે.
ઘણીવાર, stride એ width * bytes_per_pixel કરતાં વધુ હશે. આ એટલા માટે છે કારણ કે CPU અથવા GPU દ્વારા ઝડપી પ્રોસેસિંગ માટે મેમરીને ઘણીવાર હાર્ડવેર બાઉન્ડ્રીઝ (દા.ત., 32- અથવા 64-બાઇટ બાઉન્ડ્રીઝ) સાથે સંરેખિત કરવા માટે પેડ કરવામાં આવે છે. તમારે હંમેશા કોઈ ચોક્કસ હરોળમાં પિક્સેલનું મેમરી એડ્રેસ ગણવા માટે સ્ટ્રાઇડનો ઉપયોગ કરવો જ જોઈએ.
સ્ટ્રાઇડને અવગણવાથી છબીઓ ત્રાંસી અથવા વિકૃત થઈ શકે છે અને ડેટા એક્સેસ ખોટો થઈ શકે છે.
વ્યવહારુ ઉદાહરણ 1: ગ્રેસ્કેલ પ્લેનને એક્સેસ કરવું અને પ્રદર્શિત કરવું
ચાલો એક સરળ પણ શક્તિશાળી ઉદાહરણથી શરૂઆત કરીએ. વેબ પર મોટાભાગના વિડિયો I420 જેવા YUV ફોર્મેટમાં એન્કોડ થયેલા હોય છે. 'Y' પ્લેન અસરકારક રીતે છબીનું સંપૂર્ણ ગ્રેસ્કેલ પ્રતિનિધિત્વ છે. આપણે ફક્ત આ પ્લેનને બહાર કાઢી શકીએ છીએ અને તેને કેનવાસ પર રેન્ડર કરી શકીએ છીએ.
async function displayGrayscale(videoFrame) {
// આપણે માની લઈએ છીએ કે videoFrame 'I420' અથવા 'NV12' જેવા YUV ફોર્મેટમાં છે.
if (!videoFrame.format.startsWith('I4')) {
console.error('આ ઉદાહરણ માટે YUV 4:2:0 પ્લાનર ફોર્મેટની જરૂર છે.');
videoFrame.close();
return;
}
const yPlaneInfo = videoFrame.layout[0]; // Y પ્લેન હંમેશા પ્રથમ હોય છે.
// ફક્ત Y પ્લેન ડેટાને સમાવવા માટે એક બફર બનાવો.
const yPlaneData = new Uint8Array(yPlaneInfo.stride * videoFrame.codedHeight);
// Y પ્લેનને આપણા બફરમાં કૉપિ કરો.
await videoFrame.copyTo(yPlaneData, {
rect: { x: 0, y: 0, width: videoFrame.codedWidth, height: videoFrame.codedHeight },
layout: [yPlaneInfo]
});
// હવે, yPlaneData માં રો ગ્રેસ્કેલ પિક્સેલ્સ છે.
// આપણે તેને રેન્ડર કરવાની જરૂર છે. આપણે કેનવાસ માટે એક RGBA બફર બનાવીશું.
const canvas = document.getElementById('my-canvas');
canvas.width = videoFrame.displayWidth;
canvas.height = videoFrame.displayHeight;
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);
// કેનવાસ પિક્સેલ્સ પર પુનરાવર્તન કરો અને તેમને Y પ્લેન ડેટામાંથી ભરો.
for (let y = 0; y < videoFrame.displayHeight; y++) {
for (let x = 0; x < videoFrame.displayWidth; x++) {
// મહત્વપૂર્ણ: સાચો સ્રોત ઇન્ડેક્સ શોધવા માટે સ્ટ્રાઇડનો ઉપયોગ કરો!
const yIndex = y * yPlaneInfo.stride + x;
const luma = yPlaneData[yIndex];
// RGBA ImageData બફરમાં ડેસ્ટિનેશન ઇન્ડેક્સની ગણતરી કરો.
const rgbaIndex = (y * canvas.width + x) * 4;
imageData.data[rgbaIndex] = luma; // Red
imageData.data[rgbaIndex + 1] = luma; // Green
imageData.data[rgbaIndex + 2] = luma; // Blue
imageData.data[rgbaIndex + 3] = 255; // Alpha
}
}
ctx.putImageData(imageData, 0, 0);
// નિર્ણાયક: તેની મેમરીને મુક્ત કરવા માટે હંમેશા VideoFrame ને બંધ કરો.
videoFrame.close();
}
આ ઉદાહરણ કેટલાક મુખ્ય પગલાંને હાઇલાઇટ કરે છે: સાચા પ્લેન લેઆઉટને ઓળખવું, ડેસ્ટિનેશન બફર ફાળવવું, ડેટા કાઢવા માટે copyTo નો ઉપયોગ કરવો, અને નવી છબી બનાવવા માટે stride નો ઉપયોગ કરીને ડેટા પર યોગ્ય રીતે પુનરાવર્તન કરવું.
વ્યવહારુ ઉદાહરણ 2: ઇન-પ્લેસ મેનિપ્યુલેશન (સેપિયા ફિલ્ટર)
હવે ચાલો સીધું ડેટા મેનિપ્યુલેશન કરીએ. સેપિયા ફિલ્ટર એક ક્લાસિક ઇફેક્ટ છે જે અમલમાં મૂકવી સરળ છે. આ ઉદાહરણ માટે, RGBA ફ્રેમ સાથે કામ કરવું સરળ છે, જે તમને કેનવાસ અથવા WebGL સંદર્ભમાંથી મળી શકે છે.
async function applySepiaFilter(videoFrame) {
// આ ઉદાહરણ માને છે કે ઇનપુટ ફ્રેમ 'RGBA' અથવા 'BGRA' છે.
if (videoFrame.format !== 'RGBA' && videoFrame.format !== 'BGRA') {
console.error('સેપિયા ફિલ્ટર ઉદાહરણ માટે RGBA ફ્રેમની જરૂર છે.');
videoFrame.close();
return null;
}
// પિક્સેલ ડેટાને સમાવવા માટે એક બફર ફાળવો.
const frameDataSize = videoFrame.allocationSize();
const frameData = new Uint8Array(frameDataSize);
await videoFrame.copyTo(frameData);
const layout = videoFrame.layout[0]; // RGBA એક જ પ્લેન છે
// હવે, બફરમાં ડેટાને મેનિપ્યુલેટ કરો.
for (let y = 0; y < videoFrame.codedHeight; y++) {
for (let x = 0; x < videoFrame.codedWidth; x++) {
const pixelIndex = y * layout.stride + x * 4; // પ્રતિ પિક્સેલ 4 બાઇટ્સ (R,G,B,A)
const r = frameData[pixelIndex];
const g = frameData[pixelIndex + 1];
const b = frameData[pixelIndex + 2];
const tr = 0.393 * r + 0.769 * g + 0.189 * b;
const tg = 0.349 * r + 0.686 * g + 0.168 * b;
const tb = 0.272 * r + 0.534 * g + 0.131 * b;
frameData[pixelIndex] = Math.min(255, tr);
frameData[pixelIndex + 1] = Math.min(255, tg);
frameData[pixelIndex + 2] = Math.min(255, tb);
// આલ્ફા (frameData[pixelIndex + 3]) યથાવત રહે છે.
}
}
// સંશોધિત ડેટા સાથે એક *નવું* VideoFrame બનાવો.
const newFrame = new VideoFrame(frameData, {
format: videoFrame.format,
codedWidth: videoFrame.codedWidth,
codedHeight: videoFrame.codedHeight,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
// મૂળ ફ્રેમને બંધ કરવાનું ભૂલશો નહીં!
videoFrame.close();
return newFrame;
}
આ એક સંપૂર્ણ રીડ-મોડિફાઇ-રાઇટ ચક્ર દર્શાવે છે: ડેટાને બહાર કૉપિ કરો, સ્ટ્રાઇડનો ઉપયોગ કરીને તેના પર લૂપ કરો, દરેક પિક્સેલ પર ગાણિતિક રૂપાંતર લાગુ કરો, અને પરિણામી ડેટા સાથે એક નવું VideoFrame બનાવો. આ નવી ફ્રેમ પછી કેનવાસ પર રેન્ડર કરી શકાય છે, VideoEncoder ને મોકલી શકાય છે, અથવા અન્ય પ્રોસેસિંગ સ્ટેપ પર પસાર કરી શકાય છે.
પ્રદર્શન મહત્વનું છે: જાવાસ્ક્રિપ્ટ વિ. વેબએસેમ્બલી (WASM)
દરેક ફ્રેમ માટે લાખો પિક્સેલ્સ પર જાવાસ્ક્રિપ્ટમાં પુનરાવર્તન કરવું ધીમું હોઈ શકે છે (1080p ફ્રેમમાં 2 મિલિયનથી વધુ પિક્સેલ્સ, અથવા RGBA માં 8 મિલિયન ડેટા પોઇન્ટ્સ હોય છે). જ્યારે આધુનિક JS એન્જિન અતિ ઝડપી છે, ઉચ્ચ-રિઝોલ્યુશન વિડિયો (HD, 4K) ની રિયલ-ટાઇમ પ્રોસેસિંગ માટે, આ અભિગમ મુખ્ય થ્રેડ પર સરળતાથી બોજ નાખી શકે છે, જે ખરાબ વપરાશકર્તા અનુભવ તરફ દોરી જાય છે.
આ તે છે જ્યાં વેબએસેમ્બલી (WASM) એક આવશ્યક સાધન બની જાય છે. WASM તમને C++, Rust, અથવા Go જેવી ભાષાઓમાં લખેલા કોડને બ્રાઉઝરની અંદર લગભગ મૂળ ગતિએ ચલાવવાની મંજૂરી આપે છે. વિડિયો પ્રોસેસિંગ માટેનો વર્કફ્લો આ રીતે બને છે:
- જાવાસ્ક્રિપ્ટમાં: રો પિક્સેલ ડેટાને
ArrayBufferમાં મેળવવા માટેvideoFrame.copyTo()નો ઉપયોગ કરો. - WASM ને પાસ કરો: આ બફરનો સંદર્ભ તમારા કમ્પાઇલ કરેલા WASM મોડ્યુલમાં પાસ કરો. આ એક ખૂબ જ ઝડપી ઓપરેશન છે કારણ કે તેમાં ડેટાની કૉપિ શામેલ નથી.
- WASM માં (C++/Rust): તમારા અત્યંત ઑપ્ટિમાઇઝ્ડ ઇમેજ પ્રોસેસિંગ એલ્ગોરિધમ્સને સીધા મેમરી બફર પર ચલાવો. આ જાવાસ્ક્રિપ્ટ લૂપ કરતાં અનેક ગણું ઝડપી છે.
- જાવાસ્ક્રિપ્ટમાં પાછા ફરો: જ્યારે WASM સમાપ્ત થાય, ત્યારે નિયંત્રણ જાવાસ્ક્રિપ્ટ પર પાછું આવે છે. પછી તમે એક નવું
VideoFrameબનાવવા માટે સંશોધિત બફરનો ઉપયોગ કરી શકો છો.
કોઈપણ ગંભીર, રિયલ-ટાઇમ વિડિયો મેનિપ્યુલેશન એપ્લિકેશન માટે—જેમ કે વર્ચ્યુઅલ બેકગ્રાઉન્ડ, ઑબ્જેક્ટ ડિટેક્શન, અથવા જટિલ ફિલ્ટર્સ—વેબએસેમ્બલીનો લાભ લેવો એ માત્ર એક વિકલ્પ નથી; તે એક આવશ્યકતા છે.
વિવિધ પિક્સેલ ફોર્મેટ્સને હેન્ડલ કરવું (દા.ત., I420, NV12)
જ્યારે RGBA સરળ છે, ત્યારે તમને મોટાભાગે VideoDecoder માંથી પ્લાનર YUV ફોર્મેટમાં ફ્રેમ્સ મળશે. ચાલો જોઈએ કે I420 જેવા સંપૂર્ણ પ્લાનર ફોર્મેટને કેવી રીતે હેન્ડલ કરવું.
I420 ફોર્મેટમાં VideoFrame ની layout એરેમાં ત્રણ લેઆઉટ ડિસ્ક્રિપ્ટર્સ હશે:
layout[0]: Y પ્લેન (લ્યુમા). પરિમાણોcodedWidthxcodedHeight.layout[1]: U પ્લેન (ક્રોમા). પરિમાણોcodedWidth/2xcodedHeight/2.layout[2]: V પ્લેન (ક્રોમા). પરિમાણોcodedWidth/2xcodedHeight/2.
અહીં તમે ત્રણેય પ્લેન્સને એક જ બફરમાં કેવી રીતે કૉપિ કરશો તે છે:
async function extractI420Planes(videoFrame) {
const totalSize = videoFrame.allocationSize({ format: 'I420' });
const allPlanesData = new Uint8Array(totalSize);
const layouts = await videoFrame.copyTo(allPlanesData);
// layouts એ 3 PlaneLayout ઑબ્જેક્ટ્સની એરે છે
console.log('Y Plane Layout:', layouts[0]); // { offset: 0, stride: ... }
console.log('U Plane Layout:', layouts[1]); // { offset: ..., stride: ... }
console.log('V Plane Layout:', layouts[2]); // { offset: ..., stride: ... }
// તમે હવે `allPlanesData` બફરમાં દરેક પ્લેનને એક્સેસ કરી શકો છો
// તેના વિશિષ્ટ ઑફસેટ અને સ્ટ્રાઇડનો ઉપયોગ કરીને.
const yPlaneView = new Uint8Array(
allPlanesData.buffer,
layouts[0].offset,
layouts[0].stride * videoFrame.codedHeight
);
// નોંધ લો કે ક્રોમા પરિમાણો અડધા છે!
const uPlaneView = new Uint8Array(
allPlanesData.buffer,
layouts[1].offset,
layouts[1].stride * (videoFrame.codedHeight / 2)
);
const vPlaneView = new Uint8Array(
allPlanesData.buffer,
layouts[2].offset,
layouts[2].stride * (videoFrame.codedHeight / 2)
);
console.log('Accessed Y plane size:', yPlaneView.byteLength);
console.log('Accessed U plane size:', uPlaneView.byteLength);
videoFrame.close();
}
બીજું એક સામાન્ય ફોર્મેટ NV12 છે, જે સેમી-પ્લાનર છે. તેમાં બે પ્લેન્સ હોય છે: એક Y માટે, અને બીજું પ્લેન જ્યાં U અને V મૂલ્યો ઇન્ટરલીવ્ડ હોય છે (દા.ત., [U1, V1, U2, V2, ...]). વેબકોડેક્સ API આને પારદર્શક રીતે હેન્ડલ કરે છે; NV12 ફોર્મેટમાં VideoFrame ની layout એરેમાં ફક્ત બે લેઆઉટ હશે.
પડકારો અને શ્રેષ્ઠ પદ્ધતિઓ
આ નીચા સ્તરે કામ કરવું શક્તિશાળી છે, પરંતુ તે જવાબદારીઓ સાથે આવે છે.
મેમરી મેનેજમેન્ટ સર્વોપરી છે
એક VideoFrame નોંધપાત્ર પ્રમાણમાં મેમરી ધરાવે છે, જે ઘણીવાર જાવાસ્ક્રિપ્ટના ગાર્બેજ કલેક્ટરના હીપની બહાર સંચાલિત થાય છે. જો તમે આ મેમરીને સ્પષ્ટપણે મુક્ત નહીં કરો, તો તમે મેમરી લીકનું કારણ બનશો જે બ્રાઉઝર ટેબને ક્રેશ કરી શકે છે.
હંમેશા, હંમેશા જ્યારે તમે ફ્રેમ સાથે કામ પૂરું કરો ત્યારે videoFrame.close() કૉલ કરો.
અસિંક્રોનસ પ્રકૃતિ
બધો ડેટા એક્સેસ અસિંક્રોનસ છે. રેસ કન્ડિશન ટાળવા અને સરળ પ્રોસેસિંગ પાઇપલાઇન સુનિશ્ચિત કરવા માટે તમારી એપ્લિકેશનની આર્કિટેક્ચરને પ્રોમિસ અને async/await ના પ્રવાહને યોગ્ય રીતે હેન્ડલ કરવો આવશ્યક છે.
બ્રાઉઝર સુસંગતતા
વેબકોડેક્સ એક આધુનિક API છે. જ્યારે બધા મુખ્ય બ્રાઉઝર્સમાં સપોર્ટેડ છે, ત્યારે હંમેશા તેની ઉપલબ્ધતા તપાસો અને કોઈપણ વિક્રેતા-વિશિષ્ટ અમલીકરણ વિગતો અથવા મર્યાદાઓથી વાકેફ રહો. API નો ઉપયોગ કરવાનો પ્રયાસ કરતા પહેલા ફીચર ડિટેક્શનનો ઉપયોગ કરો.
નિષ્કર્ષ: વેબ વિડિયો માટે એક નવી ક્ષિતિજ
વેબકોડેક્સ API દ્વારા VideoFrame ના રો પ્લેન ડેટાને સીધો એક્સેસ અને મેનિપ્યુલેટ કરવાની ક્ષમતા વેબ-આધારિત મીડિયા એપ્લિકેશન્સ માટે એક પેરાડાઇમ શિફ્ટ છે. તે <video> એલિમેન્ટના બ્લેક બોક્સને દૂર કરે છે અને ડેવલપર્સને અગાઉ મૂળ એપ્લિકેશન્સ માટે આરક્ષિત દાણાદાર નિયંત્રણ આપે છે.
વિડિયો મેમરી લેઆઉટના મૂળભૂત સિદ્ધાંતો—પ્લેન્સ, સ્ટ્રાઇડ, અને કલર ફોર્મેટ્સ—સમજીને અને પ્રદર્શન-નિર્ણાયક કામગીરી માટે વેબએસેમ્બલીની શક્તિનો લાભ લઈને, તમે હવે સીધા બ્રાઉઝરમાં અતિ અત્યાધુનિક વિડિયો પ્રોસેસિંગ ટૂલ્સ બનાવી શકો છો. રિયલ-ટાઇમ કલર ગ્રેડિંગ અને કસ્ટમ વિઝ્યુઅલ ઇફેક્ટ્સથી લઈને ક્લાયન્ટ-સાઇડ મશીન લર્નિંગ અને વિડિયો વિશ્લેષણ સુધી, શક્યતાઓ વિશાળ છે. વેબ પર ઉચ્ચ-પ્રદર્શન, નીચા-સ્તરના વિડિયોનો યુગ ખરેખર શરૂ થઈ ગયો છે.